package com.qingfeng.medical.biz.message.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qingfeng.currency.dozer.DozerUtils;
import com.qingfeng.medical.base.handler.GeneralAuthException;
import com.qingfeng.medical.biz.auth.domain.entity.SysUser;
import com.qingfeng.medical.biz.auth.service.SysUserService;
import com.qingfeng.medical.biz.information.domain.entity.DoctorInfo;
import com.qingfeng.medical.biz.information.domain.entity.UserInfo;
import com.qingfeng.medical.biz.information.domain.vo.DiseaseDoctorVo;
import com.qingfeng.medical.biz.information.domain.vo.UserInfoDiseaseVo;
import com.qingfeng.medical.biz.information.service.DoctorInfoService;
import com.qingfeng.medical.biz.information.service.UserInfoService;
import com.qingfeng.medical.biz.message.dao.DiseaseConsultationMapper;
import com.qingfeng.medical.biz.message.domain.dto.DiseaseConsultationSaveDTO;
import com.qingfeng.medical.biz.message.domain.entity.DiseaseConsultation;
import com.qingfeng.medical.biz.message.domain.enums.CustomerTypeEnum;
import com.qingfeng.medical.biz.message.domain.enums.ReadStatusEnum;
import com.qingfeng.medical.biz.message.service.DiseaseConsultationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 病情咨询表
 *
 * @author 清风学Java
 * @date 2023-04-14 14:47:16
 */
@Service
public class DiseaseConsultationServiceImpl extends ServiceImpl<DiseaseConsultationMapper, DiseaseConsultation> implements DiseaseConsultationService {

    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private DoctorInfoService doctorInfoService;
    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private DozerUtils dozerUtils;

    /**
     * 医师列表信息
     *
     * @param depId
     * @return
     */
    @Override
    public List<DiseaseDoctorVo> doctorList(Long depId) {
        List<DoctorInfo> doctorInfoList = doctorInfoService.list(
                new LambdaQueryWrapper<DoctorInfo>()
                        .like(DoctorInfo::getDepartmentPatient, "%" + depId + "%")
        );

        if (CollUtil.isEmpty(doctorInfoList)) {
            return Collections.emptyList();
        }

        // 查询用户基础信息
        Map<Long, SysUser> sysUserMap = sysUserService.list(
                        new LambdaQueryWrapper<SysUser>()
                                .in(SysUser::getId, doctorInfoList.stream()
                                        .map(DoctorInfo::getUserId)
                                        .collect(Collectors.toList())
                                )
                )
                .stream()
                .collect(Collectors.toMap(
                                SysUser::getId,
                                Function.identity()
                        )
                );

        return doctorInfoList.stream()
                .map(d -> DiseaseDoctorVo.builder()
                        .id(d.getUserId())
                        .name(sysUserMap.get(d.getUserId()).getName())
                        .position(d.getPosition().getMsg())
                        .introduction(d.getIntroduction())
                        .headUrl(sysUserMap.get(d.getUserId()).getHeadUrl())
                        .build()
                )
                .collect(Collectors.toList());
    }

    /**
     * 保存用户咨询信息
     *
     * @param diseaseConsultationSaveDTO
     */
    @Override
    public void saveDiseaseConsultation(DiseaseConsultationSaveDTO diseaseConsultationSaveDTO) {
        baseMapper.insert(dozerUtils.map2(diseaseConsultationSaveDTO, DiseaseConsultation.class));
    }

    /**
     * 查询咨询信息
     *
     * @param userId
     * @param doctorId
     * @return
     */
    @Override
    @Transactional(rollbackFor = GeneralAuthException.class)
    public List<DiseaseConsultation> diseaseList(Long userId, Long doctorId) {
        List<DiseaseConsultation> diseaseConsultationList = baseMapper.selectList(
                new LambdaQueryWrapper<DiseaseConsultation>()
                        .eq(DiseaseConsultation::getUserId, userId)
                        .eq(DiseaseConsultation::getDoctorId, doctorId)
        );

        // 这里是前台用户查询的，所以要将所有医生发的消息变为已读
        diseaseConsultationList.stream()
                .filter(d -> d.getCustomerType().equals(CustomerTypeEnum.DOCTOR))
                .forEach(d -> d.setReadStatus(ReadStatusEnum.READ));

        // 更新数据库
        this.updateBatchById(diseaseConsultationList);

        return diseaseConsultationList;
    }

    /**
     * 查询病情咨询的用户列表
     *
     * @param userId
     * @return
     */
    @Override
    public List<UserInfoDiseaseVo> userList(Long userId) {
        // 查询医师当前所有的病情咨询信息
        List<DiseaseConsultation> diseaseConsultationList = baseMapper.selectList(
                new LambdaQueryWrapper<DiseaseConsultation>()
                        .eq(DiseaseConsultation::getDoctorId, userId)
        );

        if (CollUtil.isEmpty(diseaseConsultationList)) {
            return Collections.emptyList();
        }

        // 查询咨询的用户信息
        List<Long> userIds = diseaseConsultationList.stream()
                .map(DiseaseConsultation::getUserId)
                .distinct()
                .collect(Collectors.toList());

        List<UserInfo> userInfoList = userInfoService.list(
                new LambdaQueryWrapper<UserInfo>()
                        .in(UserInfo::getId, userIds)
        );

        // 将所有的咨询信息进行分组
        Map<Long, List<DiseaseConsultation>> diseaseConsultationMap = diseaseConsultationList.stream()
                .filter(d -> d.getCustomerType().equals(CustomerTypeEnum.PATIENT))
                .collect(Collectors.groupingBy(
                                DiseaseConsultation::getUserId
                        )
                );

        return userInfoList.stream()
                .map(u -> UserInfoDiseaseVo.builder()
                        .id(u.getId())
                        .nickName(StrUtil.isBlank(u.getNickName()) ? u.getName() : u.getNickName())
                        .headImgUrl(u.getHeadImgUrl())
                        .status(
                                diseaseConsultationMap.get(u.getId())
                                        .stream()
                                        .filter(d -> d.getReadStatus().equals(ReadStatusEnum.UNREAD))
                                        .collect(Collectors.counting()) > 0 ? 1 : 0
                        )
                        .build())
                .collect(Collectors.toList())
                .stream()
                .sorted((a1, a2) -> a1.getStatus() - a2.getStatus())
                .collect(Collectors.toList());
    }
}